package fr.grassaud.hmvc.info;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.grassaud.hmvc.component.Child;
import fr.grassaud.hmvc.component.Controller;
import fr.grassaud.hmvc.event.HMVCEvent;
import fr.grassaud.hmvc.util.HMVCIntrospector;

public class DynamicChildInfo {

    private HMVCEvent event;
    private Method method;

    
    private int controllerIndex;
    private Class<?> controllerClass;
    private String childName;
    
    private Logger logger = LoggerFactory.getLogger(DynamicChildInfo.class);

    public DynamicChildInfo(HMVCEvent event, Method m) {
	this.event = event;
	this.method = m;
	controllerIndex = -1;
	readInfo();

    }

    private void readInfo() {
	Annotation[][] annotations = method.getParameterAnnotations();
	int i =0;
	for ( Annotation[] paramAnnotation : annotations) {
	    for ( Annotation anno : paramAnnotation ) {
		if ( anno.annotationType().equals(Child.class)) {
		    Child childAnno = (Child)anno;
		    controllerIndex = i;
		    childName = childAnno.name();
		}
	    }
	    i++;
	}
	
	if ( controllerIndex == -1 ) {
	    logger.error("the method {} for event {} should have a child controller defined", method.getName(),event.getName());
	    throw new IllegalStateException("no child controller found in method");
	}
	this.controllerClass = method.getParameterTypes()[controllerIndex];
	//
	if ( !HMVCIntrospector.isControllerComponent(controllerClass) ) {
	    logger.error("ERROR, the child controller of type {} shoudl be annotated with {}", controllerClass, Controller.class);
	    throw new IllegalStateException("The child controller should be annotated with " + Controller.class);
	}
    }
    
    
    
    public Class<?> getControllerClass() {
	return this.controllerClass;
    }
    
    public int getControllerParamIndex() {
	return this.controllerIndex;
    }
    
    
    public String getControllerName() {
	return this.childName;
    }
    

    public Object[] getParameters() {
	Object[] params = new Object[method.getParameterTypes().length];
	int i = 0;
	for (Class<?> type : method.getParameterTypes()) {
	    for (Object eventParam : event.getParameters()) {
		if (type.isInstance(eventParam)) {
		    params[i] = eventParam;
		}
	    }
	    i++;
	    
	}

	return params;
    }

}
